﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text.RegularExpressions;

namespace Templates.Models
{
    [Export(typeof(TemplateFormatter))]
    public sealed class TemplateFormatter
    {
        private IEnumerable<string> Read(Regex regex, string body)
        {
            foreach (Match match in regex.Matches(body ?? string.Empty))
            {
                yield return match.Groups[1].Value;
            }
        }

        public Template Read(Template template)
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            string startChar = template.StartCharacter ?? string.Empty,
                endChar = template.EndCharacter ?? string.Empty;

            if (string.IsNullOrEmpty(endChar))
            {
                throw new InvalidOperationException("Cannot extract variables with blank end character!");
            }

            startChar = Regex.Escape(startChar);
            endChar = Regex.Escape(endChar);

            Regex regex = new Regex(startChar + "([^" + endChar + "]+)" + endChar);
            template.Variables = new List<Variable>(
                Read(regex, template.Body)
                .Distinct()
                .Select(v => new Variable { Name = v }));
            return template;
        }

        public string Write(Template template)
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            string text = template.Body ?? string.Empty;

            if (template.Variables != null)
            {
                foreach (var variable in template.Variables)
                {
                    string startChar = template.StartCharacter ?? string.Empty,
                        endChar = template.EndCharacter ?? string.Empty;
                    startChar = Regex.Escape(startChar);
                    endChar = Regex.Escape(endChar);

                    RegexOptions options = template.IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
                    Regex regex = new Regex(startChar + variable.Name + endChar, options);

                    text = regex.Replace(text, variable.Value);
                }
            }

            return text;
        }
    }
}
